﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;

namespace Region
{
    [DBObject(Table="users",PrimaryKeyPole="UserID")]
    public class User : DBObject
    {
        [DBColumn] public Int32 UserID { get; set; }
        [DBColumn] public Int32 GroupeID { get; set; }
        [DBColumn] public Int32 OtdelID { get; set; }
        [DBColumn] public Int32 Online { get; set; }
        [DBColumn] public String Name { get; set; }
        [DBColumn] public String Pass { get; set; }
        [DBColumn] public String UserInfo { get; set; }
        [DBColumn] public String Titul { get; set; }
        [DBColumn] public String FIO { get; set; }
        [DBColumn] public String FullFIO { get; set; }
        [DBColumn] public String Telefon { get; set; }
        [DBColumn] public String UserInfo2 { get; set; }
        [DBColumn] public String UserName2 { get; set; }
        [DBColumn] public String Titul2 { get; set; }
        [DBColumn] public String FullFIO2 { get; set; }
        [DBColumn] public String Access2 { get; set; }        
        public User(Engine engine, Int32 UserID,IDictionary<String,Object> Poles = null)
            : base(engine, UserID, Poles)
        {

        }
        protected Groupe m_Groupe;
        protected Dictionary<String, bool> m_Access2;
        public Otdel Otdel{get{return m_engine.getOtdel(OtdelID);}}
        public override bool read(IDictionary<String, Object> Fields)
        {
            if (!base.read(Fields)) return false;
            m_Access2 = new Dictionary<String, bool>();
            { String[] A = Access2.Split(','); Int32 n = A.Length; for (int i = 0; i < n; i++) m_Access2[A[i]] = true; }
            m_Groupe = m_engine.getGroupe(GroupeID);
            return true;
        }
        public override bool poleAccess(String PoleName) { return true; }
        public bool isAccess(String Access) 
        {
            if (!isRead()) read();
            return m_Access2.ContainsKey(Access) || m_Groupe.isAccess(Access); 
        }
        public Dictionary<String, bool> getAccessArray() 
        {
            if (!isRead()) read();
            return new Dictionary<string,bool>(m_Access2); 
        }
        public Dictionary<String, bool> getFullAccess()
        {
            if (!isRead()) read();
            var A = m_Groupe.getAccess();
            foreach (var key in m_Access2.Keys)
                A.Add(key, m_Access2[key]);
            return A; 
        }
    }
  public struct UserListLine
  {
    public Int32 UserID;
    public Int32 OtdelID;
    public String FIO;
  }
  public class UserList:DBList<UserListLine>
  {
    public UserList(Engine engine):base(engine)
    {
      DefaultPoles.Add("users.UserID");
      DefaultPoles.Add("users.OtdelID");
      DefaultPoles.Add("users.FIO");
      DefaultTables.Add("users");
      DefaultOrderBy.Add("users.FIO ASC");    
    }
    protected override void ProceessWheres(SQLParam Params,List<String> Tables, List<String> Poles,List<String> Wheres,List<String> OrderBy)
    {
        if (m_wheres.ContainsKey("Mode"))
        {
            if ((String)m_wheres["Mode"] == "User")
            {
                Poles.Clear();
                Poles.Add("users.*");
            }
        }
      Int32 ParentOtdelID,MinCountRaspor,MinCountWorkRaspor,MinCountPred;
      if (m_wheres.ContainsKey("ParentOtdelID") && (int)m_wheres["ParentOtdelID"]>0 && Int32.TryParse(m_wheres["ParentOtdelID"].ToString(), out ParentOtdelID))
      {
        Tables.Add("INNER JOIN otdel_otdel ON otdel_otdel.OtdelID=users.OtdelID");
        Wheres.Add("otdel_otdel.ParentOtdelID=@ParentOtdelID");
        Params["@ParentOtdelID"] = ParentOtdelID;        
      }
      if (m_wheres.ContainsKey("MinCountRaspor") && (int)m_wheres["MinCountRaspor"]>0 && Int32.TryParse(m_wheres["MinCountRaspor"].ToString(), out MinCountRaspor))
      {
        Tables.Add("LEFT JOIN (SELECT COUNT(*) AS Num,IspUserID FROM raspor GROUP BY IspUserID) AS ru ON ru.IspUserID=users.UserID");
        Wheres.Add("ru.Num >= @MinCountRaspor");
        Params["@MinCountRaspor"] = MinCountRaspor;        
      }
      if (m_wheres.ContainsKey("MinCountWorkRaspor") && (int)m_wheres["MinCountWorkRaspor"]>0 && Int32.TryParse(m_wheres["MinCountWorkRaspor"].ToString(), out MinCountWorkRaspor))
      {
        Tables.Add("LEFT JOIN (SELECT COUNT(*) AS Num, rasporuser.UserID FROM raspor INNER JOIN rasporuser ON rasporuser.RasporID=raspor.RasporID GROUP BY rasporuser.UserID) AS rwu ON rwu.UserID=users.UserID");
        Wheres.Add("rwu.Num >= @MinCountWorkRaspor");
        Params["@MinCountWorkRaspor"] = MinCountWorkRaspor;        
      }      
      if (m_wheres.ContainsKey("MinCountPred") && (int)m_wheres["MinCountPred"]>0 && Int32.TryParse(m_wheres["MinCountPred"].ToString(), out MinCountPred))
      {
        Tables.Add("LEFT JOIN (SELECT COUNT(*) AS Num,IspUserID FROM pred GROUP BY IspUserID) AS pu ON pu.IspUserID=users.UserID");
        Wheres.Add("pu.Num >= @MinCountPred");
        Params["@MinCountPred"] = MinCountPred;        
      }      
/*
SELECT ru.Num,users.* 
from users 
left join (SELECT COUNT(*) as Num,IspUserID from raspor group by IspUserID) as ru ON ru.IspUserID=users.UserID
where ru.Num>0
/*  */
    }
    protected override UserListLine readLine(Dictionary<String, Object> r)
    {
      var l = new UserListLine();
      l.UserID = (Int32)r["UserID"];
      l.OtdelID = (Int32)r["OtdelID"];
      l.FIO = (String)r["FIO"];
      return l;
    }
    protected override Boolean preLoadObject<User>(Dictionary<String, Object> Fields, Object PkValue)
    {
        m_engine.getUser((Int32)PkValue, Fields);
        return true;
    }
  };
  public partial class Engine
  {
    private Dictionary<Int32, User> l_Users;
    /// <summary> Загружает данные пользователей одним запросом</summary>
    /// <param name="Wheres">смотри UserList.ProceessWheres</param>
    /// <returns>Если пред загрузка удалаяь true</returns>
    public Boolean preLoadUser(IDictionary<String, Object> Wheres)
      {
          return preLoadRaspor(null, Wheres);
      }
    public Boolean preLoadUser(UserList list = null, IDictionary<String, Object> Wheres = null)
      {
          if (list == null)
              list = new UserList(this);
          Object oldMode = list.getWhere("Mode");
          list.setWhere("Mode", "User");
          if (Wheres != null)
              foreach (var w in Wheres)
                  list.setWhere(w.Key, w.Value);
          Boolean result = list.preLoad<User>();
          list.setWhere("Mode", oldMode);
          return result;
      }
    public User getUser(Int32 UserID, IDictionary<String, Object> Fields = null)
    {
        if (l_Users.ContainsKey(UserID)) return (User)l_Users[UserID];
        User user = new User(this, UserID, Fields);
        l_Users[UserID] = user;
        return user;
    }
    public User getUserFromUserName(String UserName, MySqlConnection Database = null)
    {
        SQLResult R = SQLSelect("SELECT UserID FROM users WHERE Name=@Name", new SQLParam() { { "@Name", UserName } }, Database);
        if (R.Count == 0)
            return null;
        return getUser((Int32)R[0]["UserID"]);
    }
    public User getUserFromCookieCode(String CookieCode, MySqlConnection Database = null)
    {
        SQLResult R = SQLSelect("SELECT UserID FROM users WHERE CookieCode=@CookieCode", new SQLParam() { { "@CookieCode", CookieCode } }, Database);
        if (R.Count == 0)
            return null;
        return getUser((Int32)R[0]["UserID"]);
    }
  }
}
